#include <string.h>
#include <errno.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/ring_buffer.h>

#include "serial.h"

#define LOG_MODULE_NAME serial
LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF);

#define RX_INACTIVE_TIMEOUT_US 2000000

#define UART_TX_BUFFER_SIZE 255    // 单次UART发送的最大字节数
#define UART_RING_BUFFER_SIZE 1024 // 环形缓冲区总大小

struct uart_buf
{
    uint8_t data[SERIAL_BLOCK_SIZE];
    uint32_t len;
};

static const struct device *uart_dev = DEVICE_DT_GET(DT_NODELABEL(uart0));

K_MEM_SLAB_DEFINE_STATIC(uart_rx_slab, SERIAL_BLOCK_SIZE, SERIAL_RX_BLOCK_NUM, 4);
K_MSGQ_DEFINE(uart_rx_msgq, (SERIAL_BLOCK_SIZE + 4), SERIAL_MSGQ_BLOCK_NUM, 1);

K_THREAD_STACK_DEFINE(uart_thread_stack, 1024);
struct k_thread uart_thread_data;

static struct serial_inst m_serial_inst = {0};
static rx_proccess_t m_rx_proccess = NULL;

static struct ring_buf uart_ring_buffer;
static uint8_t ring_buffer_data[UART_RING_BUFFER_SIZE];
static volatile bool uart_busy = false;

static void uart_cb(const struct device *dev, struct uart_event *evt,
                    void *user_data)
{
    struct device *uart = (struct device *)user_data;
    int err;

    switch (evt->type)
    {
    case UART_TX_DONE:
    {
        LOG_INF("Tx sent %d bytes.", evt->data.tx.len);
        if (evt->data.tx.len == 0 || evt->data.tx.buf == NULL)
        {
            return;
        }

        uint8_t *tx_data;
        size_t chunk_len = ring_buf_get_claim(&uart_ring_buffer, &tx_data, UART_TX_BUFFER_SIZE);

        if (chunk_len > 0)
        {
            // 发送下一块数据
            uart_tx(uart_dev, tx_data, chunk_len, SYS_FOREVER_MS);
            ring_buf_get_finish(&uart_ring_buffer, chunk_len); // 更新读取位置
        }
        else
        {
            uart_busy = false; // 没有数据待发送，标记UART空闲
        }
    }
    break;

    case UART_TX_ABORTED:
    {
        LOG_DBG("Tx aborted.");
        uart_busy = false;
        uint8_t *tx_data;
        size_t chunk_len = ring_buf_get_claim(&uart_ring_buffer, &tx_data, UART_TX_BUFFER_SIZE);

        if (chunk_len > 0)
        {
            // 发送下一块数据
            uart_tx(uart_dev, tx_data, chunk_len, SYS_FOREVER_MS);
            ring_buf_get_finish(&uart_ring_buffer, chunk_len); // 更新读取位置
        }
        else
        {
            uart_busy = false; // 没有数据待发送，标记UART空闲
        }
    }
    break;

    case UART_RX_RDY:
    {
        LOG_DBG("Receive data %d bytes, offset %d.", evt->data.rx.len, evt->data.rx.offset);

        struct uart_buf rx_buf_tmp = {0};
        memcpy(rx_buf_tmp.data, &evt->data.rx.buf[evt->data.rx.offset], evt->data.rx.len);
        rx_buf_tmp.len = evt->data.rx.len;

        if (k_msgq_put(&uart_rx_msgq, &rx_buf_tmp, K_NO_WAIT) != 0)
        {
            LOG_WRN("UART message queue overflow!!");
        }
    }
    break;

    case UART_RX_BUF_RELEASED:
    {
        LOG_DBG("UART_RX_BUF_RELEASED");
        k_mem_slab_free(&uart_rx_slab, (void *)evt->data.rx_buf.buf);
    }
    break;

    case UART_RX_BUF_REQUEST:
    {
        LOG_DBG("UART_RX_BUF_REQUEST");
        struct uart_buf *buf;
        err = k_mem_slab_alloc(&uart_rx_slab, (void **)&buf, K_NO_WAIT);
        if (err)
        {
            LOG_ERR("[UART_RX_BUF_REQUEST] k_mem_slab_alloc failed (err %d)", err);
            return;
        }

        err = uart_rx_buf_rsp(uart, (uint8_t *)buf, SERIAL_BLOCK_SIZE);
        if (err)
        {
            LOG_ERR("[UART_RX_BUF_REQUEST] uart_rx_buf_rsp failed (err %d)", err);
        }
    }
    break;

    case UART_RX_DISABLED:
    {
        LOG_DBG("UART_RX_DISABLED");
        struct uart_buf *buf;
        err = k_mem_slab_alloc(&uart_rx_slab, (void **)&buf, K_NO_WAIT);
        if (err)
        {
            LOG_ERR("[UART_RX_DISABLED] k_mem_slab_alloc failed (err %d)", err);
            return;
        }

        err = uart_rx_enable(uart_dev, (uint8_t *)buf, SERIAL_BLOCK_SIZE, RX_INACTIVE_TIMEOUT_US);
        if (err)
        {
            LOG_ERR("uart_rx_enable failed (err %d)", err);
        }
    }
    break;

    default:
        break;
    }
}

static int serial_tx(const uint8_t *data, uint16_t len)
{
    while (len > 0)
    {
        uint8_t *buf_ptr;
        size_t chunk_len = ring_buf_put_claim(&uart_ring_buffer, &buf_ptr, len);

        if (chunk_len == 0)
        {
            // 缓冲区已满，直接丢弃剩余数据
            LOG_WRN("Ring buffer full, discarding data.");
            return 0;
        }

        memcpy(buf_ptr, data, chunk_len);                  // 将数据直接写入环形缓冲区
        ring_buf_put_finish(&uart_ring_buffer, chunk_len); // 更新写入位置

        // 如果UART空闲，立即发送缓冲区中的数据
        if (!uart_busy)
        {
            uart_busy = true;
            uint8_t *tx_data;
            size_t send_len = ring_buf_get_claim(&uart_ring_buffer, &tx_data, UART_TX_BUFFER_SIZE);
            uart_tx(uart_dev, tx_data, send_len, SYS_FOREVER_MS);
            ring_buf_get_finish(&uart_ring_buffer, send_len); // 更新读取位置
        }

        len -= chunk_len;
        data += chunk_len;
    }
    return len;
}

static void uart_thread(void *p1, void *p2, void *p3)
{
    struct uart_buf buf;
    while (1)
    {
        if (k_msgq_get(&uart_rx_msgq, &buf, K_FOREVER) == 0)
        {
            LOG_HEXDUMP_DBG(buf.data, buf.len, "RX");
            if (m_rx_proccess)
            {
                m_rx_proccess(buf.data, buf.len);
            }
        }
    }
}

struct serial_inst *serial_init(rx_proccess_t rx_proccess_func)
{
    int err;
    struct uart_buf *rx_buf;

    if (!device_is_ready(uart_dev))
    {
        LOG_ERR("UART device not ready");
        return NULL;
    }

    m_serial_inst.tx = serial_tx;
    m_rx_proccess = rx_proccess_func;

    ring_buf_init(&uart_ring_buffer, sizeof(ring_buffer_data), ring_buffer_data);

    // allocate buffer
    err = k_mem_slab_alloc(&uart_rx_slab, (void **)&rx_buf, K_NO_WAIT);
    if (err)
    {
        LOG_ERR("[uart init] k_mem_slab_alloc failed (err %d)", err);
        return NULL;
    }

    err = uart_callback_set(uart_dev, uart_cb, (void *)uart_dev);
    if (err)
    {
        LOG_ERR("uart_callback_set failed (err %d)", err);
        return NULL;
    }

    err = uart_rx_enable(uart_dev, (uint8_t *)rx_buf, SERIAL_BLOCK_SIZE, RX_INACTIVE_TIMEOUT_US);
    if (err)
    {
        LOG_ERR("Cannot enable uart reception (err: %d)", err);
        return NULL;
    }

    k_thread_create(&uart_thread_data, uart_thread_stack,
                    K_THREAD_STACK_SIZEOF(uart_thread_stack), uart_thread, NULL,
                    NULL, NULL, 5, 0, K_NO_WAIT);

    LOG_INF("Serial init success.");
    return &m_serial_inst;
}

#if 0 // serial lib test
struct serial_inst *serial_inst = NULL;

static void serial_cb(const uint8_t *const data, uint16_t len)
{
    LOG_HEXDUMP_DBG(data, len, "RX");
}

int main(void)
{
    int err;

    serial_inst = serial_init(serial_cb);
    if (!serial_inst)
    {
        LOG_ERR("Failed to init serial lib.");
        return -1;
    }

    LOG_INF("Serial lib example start.");

    uint8_t tx_data[] = {0x48, 0x57, 0x65, 0x72, 0x00, 0x02, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00, 0x32, 0x42};
    for (;;)
    {
        serial_inst->tx(tx_data, sizeof(tx_data));
        k_msleep(100);
    }

    return 0;
}
#endif
